package br.com.datasun.biblioteca.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import br.com.datasun.biblioteca.dao.factory.ConnectionFactory;
import br.com.datasun.biblioteca.entities.Cidade;
import br.com.datasun.biblioteca.entities.Documento;
import br.com.datasun.biblioteca.entities.Endereco;
import br.com.datasun.biblioteca.entities.Estado;
import br.com.datasun.biblioteca.entities.PessoaFisica;
import br.com.datasun.biblioteca.entities.TipoDocumento;
import br.com.datasun.biblioteca.exceptions.DAOException;

public class PessoaFisicaDAO {
	private ContatoDAO contatoDAO = new ContatoDAO();

	public PessoaFisica inserir(PessoaFisica pessoaFisica) throws DAOException{
		Connection connection = null;
		PreparedStatement preparedStatement   = null;
		ResultSet resultSet = null;
		StringBuilder sql = new StringBuilder();
		sql.append("insert into pessoa_fisica (id, dt_nascimento, sexo) values (?, ?, ?)");
		try{
			connection = ConnectionFactory.createConnectionToMySQL();
			preparedStatement = connection.prepareStatement(sql.toString());
			preparedStatement.setLong(1, pessoaFisica.getId());
			java.sql.Date dataNascimento = new java.sql.Date(pessoaFisica.getDataNascimento().getTime());
			preparedStatement.setDate(2, dataNascimento);
			preparedStatement.setString(3, Character.toString(pessoaFisica.getSexo()));
			preparedStatement.execute();
			
		}catch (Exception e) {
			throw new DAOException(e);
		}finally{
			try{
				if(resultSet != null){
					resultSet.close();
				}
				if(preparedStatement != null){
					preparedStatement.close();
				}
				if(connection != null){
					connection.close();
				}
			}catch (Exception e) {
				throw new DAOException(e);
			}
		}
		return pessoaFisica;
	}	
	
	public boolean atualizarPessoaFisica(PessoaFisica pessoaFisica) throws DAOException{
		boolean result = false;
		Connection connection = null;
		PreparedStatement preparedStatement   = null;
		StringBuilder sql = new StringBuilder();
		sql.append(" update pessoa_fisica ");
		sql.append("    set dt_nascimento = ?");
		sql.append("       ,sexo = ? ");
		sql.append(" where id = ?");
		try{
			connection = ConnectionFactory.createConnectionToMySQL();
			preparedStatement = connection.prepareStatement(sql.toString());
			java.sql.Date dataNascimento = new java.sql.Date(pessoaFisica.getDataNascimento().getTime());
			preparedStatement.setDate(1, dataNascimento);
			preparedStatement.setString(2, Character.toString(pessoaFisica.getSexo()));
			preparedStatement.setLong(3, pessoaFisica.getId());
			preparedStatement.executeUpdate();
			result = true;
		}catch (Exception e) {
			throw new DAOException(e);
		}finally{
			try{
				if(preparedStatement != null){
					preparedStatement.close();
				}
				if(connection != null){
					connection.close();
				}
			}catch (Exception e) {
				throw new DAOException(e);
			}
		}
		return result;
		
	}
	
	public boolean excluirPessoaFisica(Long id) throws DAOException{
		boolean result = false;
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		StringBuilder sql = new StringBuilder();
		sql.append("delete from pessoa_fisica ");
		sql.append(" where id= ?");
		try{
			connection = ConnectionFactory.createConnectionToMySQL();
			preparedStatement = connection.prepareStatement(sql.toString());
			preparedStatement.setLong(1, id);
			preparedStatement.execute();
			result = true;
		}catch (Exception e) {
			throw new DAOException(e);
		}finally{
			try{
				if(preparedStatement != null){
					preparedStatement.close();
				}
				if(connection != null){
					connection.close();
				}
			}catch (Exception e) {
				throw new DAOException(e);
			}
		}
		return result;
	}	
	
	public List<PessoaFisica> consultaPessoaFisica(String nNome, String nEmail,String nCPF,String nRG)  throws DAOException{
		List<PessoaFisica> resultado = new ArrayList<PessoaFisica>();
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
						
		StringBuilder sql = new StringBuilder();
		sql.append("select pessoa.id,												  ");
 		sql.append("       pessoa.nome as nomepessoa,								  ");
 		sql.append("       pessoa.email,											  ");
 		sql.append("       pessoa.ativo,											  ");
		sql.append("       pessoa.id_endereco,										  "); 
 		sql.append("       pessoa_fisica.dt_nascimento,								  ");
 		sql.append("       pessoa_fisica.sexo, 										  ");
 		sql.append("       documento.id as id_documento,							  ");
 		sql.append("       documento.numero as numero_documento,					  ");
 		sql.append("       documento.id_tipo_documento								  ");
  		sql.append("  from pessoa													  ");
 		sql.append("  join pessoa_fisica on (pessoa.id = pessoa_fisica.id)            ");
 		sql.append("  left join documento on (documento.id_pessoa = pessoa_fisica.id) ");
				
		//Where
		List<String> parametrosConsulta = new ArrayList<String>();
		Integer indiceParametro =0;
		Map<Integer,String> parametrosInformadosMap = new HashMap<Integer,String>();
		if ((nNome != null)&&!("".equals(nNome))){
			parametrosConsulta.add("pessoa.nome like ? ");
			indiceParametro++;
			parametrosInformadosMap.put(indiceParametro,nNome);
		}
		if ((nEmail != null)&&!("".equals(nEmail))){
			parametrosConsulta.add("pessoa.email like ? ");
			indiceParametro++;
			parametrosInformadosMap.put(indiceParametro,nEmail);
		}
		if ((nRG != null)&&!("".equals(nRG))){
			parametrosConsulta.add("((documento.id_tipo_documento = 2)and(documento.numero like ?))");
			indiceParametro++;
			parametrosInformadosMap.put(indiceParametro,nRG);
		}
		if ((nCPF != null)&&!("".equals(nCPF))){
			parametrosConsulta.add("((documento.id_tipo_documento = 1)and(documento.numero like ?))");
			indiceParametro++;
			parametrosInformadosMap.put(indiceParametro,nCPF);
		}
					
		
		for (int i =0;i<parametrosConsulta.size();i++){
			if (i == 0){
				sql.append("where ");
				sql.append(parametrosConsulta.get(i));
			}else{
				sql.append("or ");
				sql.append(parametrosConsulta.get(i));
			}
		}
		
		//Ordenacao
		sql.append(" order by nomepessoa ");
		
		Map<Long, PessoaFisica> pessoasMap = new HashMap<Long, PessoaFisica>();
		Map<Long, List<Documento>> documentosDaPessoaMap = new HashMap<Long, List<Documento>>();		
		try{
			connection = ConnectionFactory.createConnectionToMySQL();
			preparedStatement = connection.prepareStatement(sql.toString());
			for (int j=1; j <= parametrosInformadosMap.size();j++){
				preparedStatement.setString(j, '%'+parametrosInformadosMap.get(j)+'%');
			}
			
			resultSet = preparedStatement.executeQuery();
			while (resultSet.next()) {
				Long idPessoa = resultSet.getLong("id");
				String nomePessoa = resultSet.getString("nomepessoa");
				String email = resultSet.getString("email");
				Boolean ativo = resultSet.getBoolean("ativo");
				Date dataNascimento = null;
				if (resultSet.getDate("dt_nascimento") != null) {
					dataNascimento = resultSet.getDate("dt_nascimento");
				}
				 
				String sexo = resultSet.getString("sexo");
	
				if(pessoasMap.get(idPessoa) == null){
					PessoaFisica pessoa = new PessoaFisica();
					pessoa.setId(idPessoa);
					pessoa.setNome(nomePessoa);
					pessoa.setEmail(email);
					pessoa.setAtivo(ativo);
					pessoa.setSexo(sexo.charAt(0));
					pessoa.setDataNascimento(dataNascimento);
				
					pessoasMap.put(idPessoa, pessoa);
				}
				Long idDocumento = resultSet.getLong("id_documento");
				String numeroDocumento = resultSet.getString("numero_documento");
				Long idTipoDocumento = resultSet.getLong("id_tipo_documento");
				if(idDocumento != 0){
					Documento documento = new Documento();
					documento.setId(idDocumento);
					documento.setNumero(numeroDocumento);
					documento.setTipoDocumento(TipoDocumento.getValueOf(idTipoDocumento));
					List<Documento> documentosDaPessoa = documentosDaPessoaMap.get(idPessoa);
					if(documentosDaPessoa == null){
						documentosDaPessoa = new ArrayList<Documento>();
						documentosDaPessoa.add(documento);
						documentosDaPessoaMap.put(idPessoa, documentosDaPessoa);
					}else{
						documentosDaPessoa.add(documento);
					}
				}

			}// fim do while
			for(PessoaFisica pessoa: pessoasMap.values()){
				List<Documento> documentos = documentosDaPessoaMap.get(pessoa.getId());
				pessoa.setDocumentos(documentos);
			}

			resultado.addAll(pessoasMap.values());
			
			//Carrega os contatos das pessoas
			contatoDAO.carregarContatosDe(resultado);
		}catch (Exception e) {
			throw new DAOException(e);
		}finally{
			try{
				if(resultSet != null){
					resultSet.close();
				}
				if(preparedStatement != null){
					preparedStatement.close();
				}
				if(connection != null){
					connection.close();
				}
			}catch (Exception e) {
				throw new DAOException(e);
			}
		}
		return resultado;
		
	}
	
	public List<PessoaFisica> listarComDocumentosEContatos()throws DAOException{
			List<PessoaFisica> resultado = new ArrayList<PessoaFisica>();
			Connection connection = null;
			PreparedStatement preparedStatement   = null;
			ResultSet resultSet   = null;
			StringBuilder sql = new StringBuilder();
			sql.append("select  pessoa.id,");
			sql.append(" pessoa.nome as nomepessoa,");
			sql.append(" pessoa.email,");
			sql.append(" pessoa.ativo,");
			sql.append(" pessoa.id_endereco, ");
			sql.append(" pessoa_fisica.dt_nascimento,");
			sql.append(" pessoa_fisica.sexo, ");
			sql.append(" endereco.id as id_endereco,");
			sql.append(" endereco.nm_logradouro,");
			sql.append(" endereco.numero,");
			sql.append(" endereco.cep,");
			sql.append(" endereco.nm_bairro,");
			sql.append(" endereco.complemento,");
			sql.append(" endereco.id_cidade,");
			sql.append(" cidade.nome as nome_cidade,");
			sql.append(" estado.id as id_estado,");
			sql.append(" estado.nome as nome_estado,");
			sql.append(" estado.sigla as sigla_estado,");
			sql.append(" documento.id as id_documento,");
			sql.append(" documento.numero as numero_documento,");
			sql.append(" documento.id_tipo_documento");
			sql.append("  from pessoa");
			sql.append(" join pessoa_fisica on (pessoa.id = pessoa_fisica.id)");
			sql.append(" left join endereco on (pessoa.id_endereco = endereco.id)");
			sql.append(" left join cidade on (endereco.id_cidade = cidade.id)");
			sql.append(" left join estado on (estado.id = cidade.id_estado)");
			sql.append(" left join documento on (documento.id_pessoa = pessoa_fisica.id)" );
			sql.append(" order by nomepessoa");
			Map<Long, PessoaFisica> pessoasMap = new HashMap<Long, PessoaFisica>();
			Map<Long, List<Documento>> documentosDaPessoaMap = new HashMap<Long, List<Documento>>();
			try{
				connection = ConnectionFactory.createConnectionToMySQL();
				preparedStatement = connection.prepareStatement(sql.toString());
				resultSet = preparedStatement.executeQuery();
				while (resultSet.next()) {
					long idPessoa = resultSet.getLong("id");
					String nomePessoa = resultSet.getString("nomepessoa");
					String email = resultSet.getString("email");
					Boolean ativo = resultSet.getBoolean("ativo");
					Date dataNascimento = null;
					if (resultSet.getDate("dt_nascimento") != null) {
						dataNascimento = resultSet.getDate("dt_nascimento");
					}
					String sexo = resultSet.getString("sexo");
		

					if(pessoasMap.get(idPessoa) == null){
						PessoaFisica pessoa = new PessoaFisica();
						pessoa.setId(idPessoa);
						pessoa.setNome(nomePessoa);
						pessoa.setEmail(email);
						pessoa.setAtivo(ativo);
						pessoa.setSexo(sexo.charAt(0));
						pessoa.setDataNascimento(dataNascimento);
						
						Endereco endereco = new Endereco();
						endereco.setId(resultSet.getLong("id_endereco"));
						endereco.setNmLogradouro(resultSet.getString("nm_logradouro"));
						endereco.setNumero(resultSet.getString("numero"));
						endereco.setCep(resultSet.getString("cep"));
						endereco.setBairro(resultSet.getString("nm_bairro"));
						endereco.setComplemento(resultSet.getString("complemento"));					
						
						Cidade cidade = new Cidade();
						cidade.setId(resultSet.getLong("id_cidade"));
						cidade.setNome(resultSet.getString("nome_cidade"));
						Estado estado = new Estado();
						estado.setId(resultSet.getLong("id_estado"));
						estado.setNome(resultSet.getString("nome_estado"));
						estado.setSigla(resultSet.getString("sigla_estado"));
						cidade.setEstado(estado);
						endereco.setCidade(cidade);
						pessoa.setEndereco(endereco);
						
						pessoasMap.put(idPessoa, pessoa);
					}
					long idDocumento = resultSet.getLong("id_documento");
					String numeroDocumento = resultSet.getString("numero_documento");
					long idTipoDocumento = resultSet.getLong("id_tipo_documento");
					if(idDocumento != 0){
						Documento documento = new Documento();
						documento.setId(idDocumento);
						documento.setNumero(numeroDocumento);
						documento.setTipoDocumento(TipoDocumento.getValueOf(idTipoDocumento));
						List<Documento> documentosDaPessoa = documentosDaPessoaMap.get(idPessoa);
						if(documentosDaPessoa == null){
							documentosDaPessoa = new ArrayList<Documento>();
							documentosDaPessoa.add(documento);
							documentosDaPessoaMap.put(idPessoa, documentosDaPessoa);
						}else{
							documentosDaPessoa.add(documento);
						}
					}

				}// fim do while
				for(PessoaFisica pessoa: pessoasMap.values()){
					List<Documento> documentos = documentosDaPessoaMap.get(pessoa.getId());
					pessoa.setDocumentos(documentos);
				}
	
				resultado.addAll(pessoasMap.values());
				
				//Carrega os contatos das pessoas
				contatoDAO.carregarContatosDe(resultado);
			}catch (Exception e) {
				throw new DAOException(e);
			}finally{
				try{
					if(resultSet != null){
						resultSet.close();
					}
					if(preparedStatement != null){
						preparedStatement.close();
					}
					if(connection != null){
						connection.close();
					}
				}catch (Exception e) {
					throw new DAOException(e);
				}
			}
			return resultado;
		}
	
	public boolean existePessoaFisicaComONome(PessoaFisica pessoaFisica) throws DAOException{
		
		boolean resultado = false;
		Connection connection = null;
		PreparedStatement preparedStatement   = null;
		ResultSet resultSet   = null;
		StringBuilder sql = new StringBuilder();
		sql.append("select p.id, ");
		sql.append("       p.nome ");
		sql.append("  from pessoa_fisica pf,");
		sql.append("       pessoa p ");
		sql.append(" where pf.id = p.id ");
		sql.append("   and p.nome like ?");
		sql.append("   and p.id <> ?"); //So Traz Registro se o id for diferente
		try{
			//conecta ao banco de dados
			connection = ConnectionFactory.createConnectionToMySQL();
			preparedStatement = connection.prepareStatement(sql.toString());
			preparedStatement.setString(1, pessoaFisica.getNome());
			preparedStatement.setLong(2, pessoaFisica.getId());
			//executa a consulta
			resultSet = preparedStatement.executeQuery();
			//gera os beans/dtos com o resultado da consulta
			if (resultSet.next()) {
				Long id = resultSet.getLong("id");
				String nome = resultSet.getString("nome");
				resultado = true;
			}
		}catch (Exception e) {
			throw new DAOException(e);
		}finally{
			try{
				if(resultSet != null){
					resultSet.close();
				}
				if(preparedStatement != null){
					preparedStatement.close();
				}
				if(connection != null){
					connection.close();
				}
			}catch (Exception e) {
				throw new DAOException(e);
			}
		}
		return resultado;
	}
}
